/*
 * BibBoardOpsTest.c
 *
 *  Created on: Dec 3, 2012
 *      Author: Larry.Li
 */

#include "TestUtils.h"
#include "../BitBoard.h"
#include "../BitBoardOps.h"

int initBitBoardOpsTestSuite(void) {
	return 0;
}
int cleanBitBoardOpsTestSuite(void) {
	return 0;
}

void test_bitBoardAND(void) {
	BitBoard leftOperand, rightOperand, result;
	leftOperand.startingBits = 0x1UL;
	leftOperand.middleBits = 0x2UL;
	leftOperand.endingBits = 0x3UL;

	rightOperand.startingBits = 0x1UL;
	rightOperand.middleBits = 0x1UL;
	rightOperand.endingBits = 0x2UL;

	result = bitBoardAND(&leftOperand, &rightOperand);

	CU_ASSERT_EQUAL(result.startingBits, 0x1UL);
	CU_ASSERT_EQUAL(result.middleBits, 0x0UL);
	CU_ASSERT_EQUAL(result.endingBits, 0x2UL);
}

void test_bitBoardOR(void) {
	BitBoard leftOperand, rightOperand, result;
	leftOperand.startingBits = 0x1UL;
	leftOperand.middleBits = 0x2UL;
	leftOperand.endingBits = 0x3UL;

	rightOperand.startingBits = 0x1UL;
	rightOperand.middleBits = 0x1UL;
	rightOperand.endingBits = 0x2UL;

	result = bitBoardOR(&leftOperand, &rightOperand);

	CU_ASSERT_EQUAL(result.startingBits, 0x1UL);
	CU_ASSERT_EQUAL(result.middleBits, 0x3UL);
	CU_ASSERT_EQUAL(result.endingBits, 0x3UL);
}

void test_bitBoardXOR(void) {
	BitBoard leftOperand, rightOperand, result;
	leftOperand.startingBits = 0x1UL;
	leftOperand.middleBits = 0x2UL;
	leftOperand.endingBits = 0x3UL;

	rightOperand.startingBits = 0x1UL;
	rightOperand.middleBits = 0x1UL;
	rightOperand.endingBits = 0x2UL;

	result = bitBoardXOR(&leftOperand, &rightOperand);

	CU_ASSERT_EQUAL(result.startingBits, 0x0UL);
	CU_ASSERT_EQUAL(result.middleBits, 0x3UL);
	CU_ASSERT_EQUAL(result.endingBits, 0x1UL);
}

void test_getFileBitBoardFromLowest10Bits() {
	int allFileBitArray[1024][10];
	genAllPossibleBitArrayOfFile(allFileBitArray);

	int bitArray[90];
	BitBoard board;
	int i, j, k;
	for (i = 0; i < 1024; i++) {
		for (j = 0; j < 9; j++) {
			board = getFileBitBoardFromLowest10Bits(i, j);
			genBitBoardArrayMapping(&board, bitArray);
			for (k = 0; k < 10; k++) {
				CU_ASSERT_EQUAL(bitArray[k * 9 + j], allFileBitArray[i][k]);
			}
		}
	}
}

void test_getRankBitBoardFromLowest9Bits() {
	int allRankBitArray[512][9];
	genAllPossibleBitArrayOfRank(allRankBitArray);

	int bitArray[90];
	BitBoard board;
	int i, j, k;
	for (i = 0; i < 512; i++) {
		for (j = 0; j < 10; j++) {
			board = getRankBitBoardFromLowest9Bits(i, j);
			genBitBoardArrayMapping(&board, bitArray);
			for (k = 0; k < 9; k++) {
				CU_ASSERT_EQUAL(bitArray[j * 9 + k], allRankBitArray[i][k]);
			}
		}
	}
}

void test_isBitBoardEmpty() {
	BitBoard board = emptyBoard();
	CU_ASSERT_TRUE(isBitBoardEmpty(&board));
}
void test_bitBoardLeftShift() {
	BitBoard board;
	int i;
	unsigned long mask = 0x1UL;
	for (i = 0; i < 32; i++) {
		board = emptyBoard();
		board.startingBits = 0x1UL;
		bitBoardLeftShift(&board, i);
		CU_ASSERT_EQUAL(board.startingBits, mask << i);
		CU_ASSERT_EQUAL(board.middleBits, 0);
		CU_ASSERT_EQUAL(board.endingBits, 0);
	}
	for (i = 32; i < 64; i++) {
		board = emptyBoard();
		board.startingBits = 0x1UL;
		bitBoardLeftShift(&board, i);
		CU_ASSERT_EQUAL(board.startingBits, 0);
		CU_ASSERT_EQUAL(board.middleBits, mask << (i - 32));
		CU_ASSERT_EQUAL(board.endingBits, 0);
	}
	for (i = 64; i < 90; i++) {
		board = emptyBoard();
		board.startingBits = 0x1UL;
		bitBoardLeftShift(&board, i);
		CU_ASSERT_EQUAL(board.startingBits, 0);
		CU_ASSERT_EQUAL(board.middleBits, 0);
		CU_ASSERT_EQUAL(board.endingBits, mask << (i - 64));
	}

}

void test_getBitBoardBitsOfRank() {
	BitBoard board;
	int i;
	unsigned long j, k;
	for (i = 0; i < 3; i++) {
		for (j = 0; j < 512; j++) {
			board.startingBits = j << (i * 9);
			board.middleBits = 0;
			board.endingBits = 0;
			CU_ASSERT_EQUAL(getBitBoardBitsOfRank(i,&board), j);
		}
	}
	//when i = 3
	for (k = 0; k < 16; k++) {
		for (j = 0; j < 32; j++) {
			board.startingBits = j << 27;
			board.middleBits = k;
			board.endingBits = 0;
			CU_ASSERT_EQUAL(getBitBoardBitsOfRank(3,&board), j |(k << 5));
		}
	}
	for (i = 4; i < 7; i++) {
		for (j = 0; j < 512; j++) {
			board.startingBits = 0;
			board.middleBits = j << ((i - 4) * 9 + 4);
			board.endingBits = 0;
			CU_ASSERT_EQUAL(getBitBoardBitsOfRank(i,&board), j);
		}
	}
	//when i = 7
	for (k = 0; k < 2; k++) {
		for (j = 0; j < 256; j++) {
			board.startingBits = 0;
			board.middleBits = k << 31;
			board.endingBits = j;
			CU_ASSERT_EQUAL(getBitBoardBitsOfRank(7, &board), (j << 1)| k);
		}
	}
	for (i = 8; i < 10; i++) {
		for (j = 0; j < 512; j++) {
			board.startingBits = 0;
			board.middleBits = 0;
			board.endingBits = j << ((i - 8) * 9 + 8);
			CU_ASSERT_EQUAL(getBitBoardBitsOfRank(i,&board), j);
		}
	}
}
void test_getRotatedBitBoardBitsOfRank() {
	BitBoard board;
	int i;
	unsigned long j, k;
	for (i = 0; i < 3; i++) {
		for (j = 0; j < 1024; j++) {
			board.startingBits = j << (i * 10);
			board.middleBits = 0;
			board.endingBits = 0;
			CU_ASSERT_EQUAL(getRotatedBitBoardBitsOfRank(i,&board), j);
		}
	}
	//when i = 3
	for (k = 0; k < 256; k++) {
		for (j = 0; j < 4; j++) {
			board.startingBits = j << 30;
			board.middleBits = k;
			board.endingBits = 0;
			CU_ASSERT_EQUAL(getRotatedBitBoardBitsOfRank(3,&board),
					j |(k << 2));
		}
	}
	for (i = 4; i < 6; i++) {
		for (j = 0; j < 1024; j++) {
			board.startingBits = 0;
			board.middleBits = j << ((i - 4) * 10 + 8);
			board.endingBits = 0;
			CU_ASSERT_EQUAL(getRotatedBitBoardBitsOfRank(i,&board), j);
		}
	}
	//when i = 6
	for (k = 0; k < 64; k++) {
		for (j = 0; j < 16; j++) {
			board.startingBits = 0;
			board.middleBits = j << 28;
			board.endingBits = k;
			CU_ASSERT_EQUAL(getRotatedBitBoardBitsOfRank(6, &board),
					j |(k << 4));
		}
	}
	for (i = 7; i < 9; i++) {
		for (j = 0; j < 1024; j++) {
			board.startingBits = 0;
			board.middleBits = 0;
			board.endingBits = j << ((i - 7) * 10 + 6);
			CU_ASSERT_EQUAL(getRotatedBitBoardBitsOfRank(i, &board), j);
		}
	}
}
void test_countBitBoardTotalBits() {
	BitBoard board =
			{ .startingBits = 0x1, .middleBits = 0x3, .endingBits = 0xF };
	CU_ASSERT_EQUAL(countBitBoardTotalBits(&board), 7);
}
void test_bitBoardLSB() {
	BitBoard board =
			{ .startingBits = 0x2, .middleBits = 0x3, .endingBits = 0xA };
	CU_ASSERT_EQUAL(bitBoardLSB(&board), 1);
}
void test_bitBoardMSB() {
	BitBoard board =
			{ .startingBits = 0x1, .middleBits = 0x3, .endingBits = 0x1 };
	CU_ASSERT_EQUAL(bitBoardMSB(&board), 64);
}

void BitBoardOpsTestSetUp() {
	CU_pSuite pSuite = CU_add_suite("Suite_BitBoardOpsTest",
			initBitBoardOpsTestSuite, cleanBitBoardOpsTestSuite);
	CU_add_test(pSuite, "test_bitBoardAND", test_bitBoardAND);
	CU_add_test(pSuite, "test_bitBoardOR", test_bitBoardOR);
	CU_add_test(pSuite, "test_bitBoardXOR", test_bitBoardXOR);
	CU_add_test(pSuite, "test_isBitBoardEmpty", test_isBitBoardEmpty);
	CU_add_test(pSuite, "test_bitBoardLeftShift", test_bitBoardLeftShift);
	CU_add_test(pSuite, "test_getBitBoardBitsOfRank",
			test_getBitBoardBitsOfRank);
	CU_add_test(pSuite, "test_getRotatedBitBoardBitsOfRank",
			test_getRotatedBitBoardBitsOfRank);
	CU_add_test(pSuite, "test_countBitBoardTotalBits",
			test_countBitBoardTotalBits);
	CU_add_test(pSuite, "test_bitBoardLSB", test_bitBoardLSB);
	CU_add_test(pSuite, "test_bitBoardMSB", test_bitBoardMSB);
	CU_add_test(pSuite, "test_getFileBitBoardFromLowest10Bits",
			test_getFileBitBoardFromLowest10Bits);
	CU_add_test(pSuite, "test_getRankBitBoardFromLowest9Bits",
			test_getRankBitBoardFromLowest9Bits);
}
